package com.fast.ThreadPoolFactory;

import cn.hutool.core.thread.NamedThreadFactory;

import java.util.concurrent.*;

/**
 * CompletableFuture
 * 主要是用于A或B有一个执行成功，然后执行C
 * <p>
 * runAfterBoth   A或B有一个执行完了，不要A和B的结果，再执行C，无返回结果
 * thenAcceptBoth A或B有一个都执行完了，需要A和B的结果，再执行C，无返回结果
 * thenCombine    A或B有一个都执行完了，需要A和B的结果，再执行C，有返回结果
 *
 * @author hjw
 * @since 2022年07月17日 18:13:00
 */
public class CF5_runAfterEither_thenAcceptEither_thenCombine {

    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors() * 2,
            Runtime.getRuntime().availableProcessors() * 2,
            10,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(300),
            new NamedThreadFactory("core_thread_pool_", true),
            new ThreadPoolExecutor.AbortPolicy()
    );

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("主线程开始了-----------");


        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            System.out.println("A线程" + Thread.currentThread().getName() + "--------把任务A执行完了");
            return "hello";
        }, threadPoolExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {

            try {
                java.lang.Thread.sleep(3000);
                System.out.println("B线程" + Thread.currentThread().getName() + "--------把任务B执行完了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "world";
        }, threadPoolExecutor);

        //1.A或B有一个执行完了，不要A和B的结果，再执行C，无返回结果
        futureA.runAfterEitherAsync(futureB, () -> System.out.println("任务C执行完了"), threadPoolExecutor);


        //2.A或B有一个都执行完了，需要A和B的结果，再执行C，无返回结果
        futureA.acceptEitherAsync(futureB, (f) -> {
            System.out.println("任务C的输出结果:" + f );
        }, threadPoolExecutor);

        //3.A或B有一个都执行完了，需要A和B的结果，再执行C，有返回结果
        CompletableFuture<String> futureC = futureA.applyToEitherAsync(futureB, (f) -> {
            System.out.println("任务C执行完了有返回值");
            return f;
        }, threadPoolExecutor);
        System.out.println("futureC返回值 = " + futureC.get());
        System.out.println("主线程结束了--------------");
    }
}
